import 'package:casdon/modules/recipe/data/model/recipe_favorite_model.dart';
import 'package:casdon/modules/recipe/domain/states/recipe_favorite_list_state.dart';
import 'package:casdon/modules/recipe/domain/usecase/recipe_favorite_list_usecase.dart';

import 'package:flutter_riverpod/flutter_riverpod.dart';

class RecipeFavoriteListNotifier
    extends AutoDisposeAsyncNotifier<RecipeFavoriteListState> {
  final int pageSize = 20;
  bool _isRefreshing = false;
  KeepAliveLink? _keepAliveLink;

  @override
  Future<RecipeFavoriteListState> build() async {
    ref.onDispose(() {
      _keepAliveLink?.close();
      _keepAliveLink = null;
    });
    ref.onResume(() {
      Future.microtask(() => _refreshSilently());
    });

    final cached = state.valueOrNull;
    if (cached != null && cached.data.isNotEmpty) {
      _updateKeepAlive(cached);
      Future.microtask(() => _refreshSilently());
      return cached;
    }

    final fresh = await _fetchData(page: 1);
    _updateKeepAlive(fresh);
    return fresh;
  }

  Future<void> refresh() async {
    await _refreshSilently(force: true);
  }

  Future<void> loadMore() async {
    final current = state.valueOrNull;
    if (current == null || current.isLoadingMore || !current.hasMore) return;

    state = AsyncValue.data(current.copyWith(isLoadingMore: true));
    final nextPage = current.page + 1;

    try {
      final nextState = await _fetchData(page: nextPage, previous: current);
      if (nextState.data.isEmpty || nextState.page == current.page) {
        final fallback = current.copyWith(isLoadingMore: false, hasMore: false);
        state = AsyncValue.data(fallback);
        _updateKeepAlive(fallback);
        return;
      }

      final merged = current.copyWith(
        data: [...current.data, ...nextState.data],
        page: nextPage,
        totalSize: nextState.totalSize,
        isLoadingMore: false,
        hasMore: nextState.hasMore,
      );

      state = AsyncValue.data(merged);
      _updateKeepAlive(merged);
    } catch (_) {
      final fallback = current.copyWith(isLoadingMore: false);
      state = AsyncValue.data(fallback);
      _updateKeepAlive(fallback);
    }
  }

  Future<void> _refreshSilently({bool force = false}) async {
    if (_isRefreshing) return;
    _isRefreshing = true;
    final previous = state.valueOrNull;
    try {
      final fresh = await _fetchData(page: 1, previous: previous);
      state = AsyncValue.data(fresh);
      _updateKeepAlive(fresh);
    } catch (_) {
      if (force && previous != null) {
        state = AsyncValue.data(previous);
      }
    } finally {
      _isRefreshing = false;
    }
  }

  Future<RecipeFavoriteListState> _fetchData({
    required int page,
    RecipeFavoriteListState? previous,
  }) async {
    final fallback = previous ?? state.valueOrNull;
    try {
      final ret = await ref
          .read(recipeFavoriteListUsecaseProvider)
          .execute(pageNum: page, pageSize: pageSize);

      final items = RecipeFavoriteModel.listFromApi(ret?.rows ?? []);
      if (items.isEmpty) {
        return RecipeFavoriteListState(
          data: const [],
          page: page,
          totalSize: ret?.total ?? 0,
          pageSize: pageSize,
          isLoadingMore: false,
          hasMore: false,
        );
      }

      final consumed = (page - 1) * pageSize + items.length;

      return RecipeFavoriteListState(
        data: items,
        page: page,
        totalSize: ret!.total,
        pageSize: pageSize,
        isLoadingMore: false,
        hasMore: ret.total > consumed,
      );
    } catch (_) {
      return fallback ??
          RecipeFavoriteListState.initial().copyWith(
            page: page,
            pageSize: pageSize,
          );
    }
  }

  void _updateKeepAlive(RecipeFavoriteListState data) {
    if (data.data.isNotEmpty) {
      _keepAliveLink ??= ref.keepAlive();
    } else {
      _keepAliveLink?.close();
      _keepAliveLink = null;
    }
  }
}

final recipeFavoriteListNotifierProvider =
    AutoDisposeAsyncNotifierProvider<
      RecipeFavoriteListNotifier,
      RecipeFavoriteListState
    >(RecipeFavoriteListNotifier.new);
